home *** CD-ROM | disk | FTP | other *** search
/ Gigarom 1 / Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso / FILES / BBS / HERMES / ProtMover6.1.cpt / ASCII / ASCII.c < prev    next >
C/C++ Source or Header  |  1990-05-29  |  7KB  |  356 lines

  1. /*    ASCII Transfer External for Hermes © 1990 By John Raymonds.
  2.  
  3.     Written in THINK C 4.0.1 as an example external for Hermes protocol
  4.     developers.  Use of any code shown below in any program other than
  5.     an external to be used with Hermes requires written permission from
  6.     the author:
  7.     
  8.     John Raymonds
  9.     76174,205 (Compuserve)
  10.     D3885 (AppleLink)
  11.     
  12.     Comments and suggestions are welcome.
  13.     
  14.     040590    JR    -    Fixed Send.c (added startTime, bytesDone reset,
  15.                     and bytesTotal set)
  16.                     
  17.     050190    JR    -    Changed read.c and write.c to support new Hermes.h
  18.                     information.  Added ++prp->filesDone in Receive.c
  19.                     so Hermes knows it was a good upload.
  20.                     
  21.     052290    JR    -    Changed over to the new Protocol Mover interface.
  22.     
  23.     052990    JR    -    See the version history in the About notes for
  24.                     changes.
  25.     
  26. */
  27.  
  28. #include "Protocol.h"
  29. #include "ASCII.h"
  30.  
  31. #include <:Mac #includes:SetUpA4.h>
  32.  
  33. ProtoRecPtr PRP;
  34. ProtoGloPtr    PGP;
  35.  
  36.  
  37. pascal OsErr main(message, prp, refCon)
  38. register int message;
  39. register ProtoRecPtr prp;
  40. long refCon;
  41. {
  42.     register OsErr err;
  43.     register ProtoGloPtr pgp;
  44.     int doProtocol();
  45.     RememberA0();
  46.     SetUpA4();
  47.     PRP = prp;
  48.     err = noErr;
  49.     if (!prp->protoData) {
  50.         /*    set up external globals if they do not exist */
  51.         prp->protoData = NewHandle((long) sizeof(ProtoGloRec));
  52.         err = MemError();
  53.         if (!err) {
  54.             /*    let's lock the globals down and keep them locked until
  55.                 we exit the external.
  56.             */
  57.             MoveHHi(prp->protoData);
  58.             HLock(prp->protoData);
  59.             /*    set up a global pointer to the globals we just allocated */
  60.             PGP = *((ProtoGloHand) prp->protoData);
  61.             /*    make it a register variable since we will use it a
  62.                 number of times...
  63.             */
  64.             pgp = PGP;
  65.             ClearBlock(pgp, (long) sizeof(ProtoGloRec));
  66.             /*    make a zero length handle for the StackSaver */
  67.             pgp->SSR.stackData = NewHandle(0L);
  68.             err = MemError();
  69.             if (err) {
  70.                 HUnlock(prp->protoData);
  71.                 DisposHandle(prp->protoData);
  72.                 prp->protoData = 0L;
  73.             }
  74.             else {
  75.                 /*    initialize our globals... */
  76.                 pgp->MIOPin.ioRefNum = prp->mRefIn;
  77.                 pgp->MIOPout.ioRefNum = prp->mRefOut;
  78.                 RWPrefs(FALSE);
  79.             }
  80.         }
  81.     }
  82.     else {
  83.         /*    set up a global pointer to the globals we allocated before */
  84.         PGP = *((ProtoGloHand) prp->protoData);
  85.         pgp = PGP;
  86.     }
  87.     if (!err) {
  88.         /*    use the StackSaver JumpBack routine to enter our code...
  89.         
  90.             On the first call (handle size of pgp->SSR = 0) JumpBack
  91.             will simply call doProtocol which is defined elsewhere.
  92.             
  93.             On calls generated after a Return was executed JumpBack
  94.             will restore the stack to the state it was in during the
  95.             call the Return and being execution there.
  96.         */
  97.         err = JumpBack(message, prp, refCon, &pgp->SSR, doProtocol);
  98.         if (err) {
  99.             /*    external has returned with a non-zero result. We are
  100.                 done so dispose of all of our stuff.
  101.             */
  102.             if (prp->protoData) {
  103.                 if (pgp->SSR.stackData) {
  104.                     DisposHandle(pgp->SSR.stackData);
  105.                 }
  106.                 HUnlock(prp->protoData);
  107.                 DisposHandle(prp->protoData);
  108.                 prp->protoData = 0L;
  109.             }
  110.         }
  111.     }
  112.     RestoreA4();
  113.     return(err);
  114. }
  115.  
  116. /*    This is the routine pasted to JumpBack.  Notice that the arguments
  117.     are the same as those defined for the external itself.  As note that
  118.     all functions (unlike the external itself) use 'C' calling conventions.
  119. */
  120.  
  121. int doProtocol(message, prp, refCon)
  122. int message;
  123. ProtoRecPtr prp;
  124. long refCon;
  125. {
  126.     register OsErr err;
  127.     err = noErr;
  128.     switch(message) {
  129.     case SEND:
  130.         err = SendASCII();
  131.         break;
  132.     case RECEIVE:
  133.         err = RecvASCII();
  134.         break;
  135.     case SETPREFS:
  136.         doSetPrefs();
  137.     default:
  138.         err = 128;
  139.         break;
  140.     }
  141.     /*    make sure our async send buffers are written out */
  142.     FlushWrite();
  143.     return(err);
  144. }
  145.  
  146. tellerror(errornum)
  147. int errornum;
  148. {
  149.     /*    set the errReason */
  150.     SetError(errornum);
  151.     /*    immediately return to Hermes to show error: timeOut = 0 */
  152.     Return(0, &PGP->SSR);
  153. }
  154.  
  155. SetError(errornum)
  156. register int errornum;
  157. {
  158.     register int i;
  159.     register StringPtr eText;
  160.     register ProtoRecPtr prp;
  161.     Str255 errText, nText;
  162.     prp = PRP;
  163.     ++PGP->errCount;
  164.     switch(errornum) {
  165.     case TIMEOUT:
  166.         eText = (StringPtr) "\pTimeout";
  167.         break;
  168.     case TOOMANYERR:
  169.         eText = (StringPtr) "\pToo many errors";
  170.         break;
  171.     case NOTTEXT:
  172.         eText = (StringPtr) "\pFile was not 'TEXT'";
  173.         break;
  174.     case NOCONTINUE:
  175.         eText = (StringPtr) "\pPause not continued";
  176.         break;
  177.     default:
  178.         eText = (StringPtr) "\pMac OS Error";
  179.         break;
  180.     }
  181.     /*    dispose of any error string that might already be there for some
  182.         reason.
  183.     */
  184.     if (prp->errReason) {
  185.         DisposHandle(prp->errReason);
  186.     }
  187.     /*    show the error list */
  188.     errText[0] = 0;
  189.     for (i = 0; i<3; i++) {
  190.         if (!PGP->errList[i]) {
  191.             break;
  192.         }
  193.         NumToString((long) PGP->errList[i], nText);
  194.         Pstrcat(errText, nText);
  195.         Pstrcad(errText, ',');
  196.     }
  197.     /*    tack on the current error */
  198.     NumToString((long) errornum, nText);
  199.     Pstrcat(errText, nText);
  200.     Pstrcat(errText, "\p = ");
  201.     Pstrcat(errText, eText);
  202.     Pstrcat(errText, "\p (");
  203.     NumToString((long) PGP->errCount, nText);
  204.     Pstrcat(errText, nText);
  205.     Pstrcat(errText, "\p errors)");
  206.     prp->errReason = NewString(errText);
  207.     prp->F.B.newError = TRUE;
  208.     /*    rotate error list */
  209.     PGP->errList[2] = PGP->errList[1];
  210.     PGP->errList[1] = PGP->errList[0];
  211.     /*    add current error to the list */
  212.     PGP->errList[0] = errornum;
  213.     /*    This routine uses a lot of stack space so we are not going to
  214.         do a Return here.
  215.     */
  216. }
  217.  
  218. ClearBlock(aPtr, size)
  219. register Ptr aPtr;
  220. register long size;
  221. {
  222.     asm {
  223.                 tst.l    size
  224.                 beq.s    @theEnd
  225.                 btst.l    #0, size
  226.                 beq.s    @even
  227. ;
  228. ; size is odd so we must clear by byte
  229. ;
  230. @loop1            clr.b    (aPtr)+
  231.                 subq.l    #1, size
  232.                 bne.s    @loop1
  233.                 bra.s    @theEnd
  234. @even            btst.l    #1, size
  235.                 beq.s    @loop3
  236. ;
  237. ; size is not a multiple of 4 so we must clear by word
  238. ;
  239. @loop2            clr.w    (aPtr)+
  240.                 subq.l    #2, size
  241.                 bne.s    @loop2
  242.                 bra.s    @theEnd
  243. ;
  244. ; size is a multiple of 4 so we can clear by long
  245. ;
  246. @loop3            clr.l    (aPtr)+
  247.                 subq.l    #4, size
  248.                 bne.s    @loop3
  249. @theEnd
  250.     }
  251. }
  252.  
  253. Pstrcpy(s, t)
  254. register StringPtr s, t;
  255. {
  256.     register int i;
  257.     asm {
  258.                 clr.w    i
  259.                 move.b    (t), i
  260. @loop            move.b    (t)+, (s)+
  261.                 dbf        i, @loop
  262.     }
  263. }    
  264.  
  265. Pstrcat(s, t)
  266. register StringPtr s, t;
  267. {
  268.     register int i;
  269.     asm {
  270.                 move.l    s, a0
  271.                 clr.w    i
  272.                 move.b    (s)+, i
  273.                 adda.w    i, s
  274.                 move.b    (t)+, i
  275.                 beq.s    @theEnd
  276.                 add.b    i, (a0)
  277.                 subq.w    #1, i
  278. @loop            move.b    (t)+, (s)+
  279.                 dbf        i, @loop
  280. @theEnd
  281.     }
  282. }
  283.  
  284. Pstrcad(s, c)
  285. register StringPtr s;
  286. register char c;
  287. {
  288.     register int i;
  289.     asm {
  290.                 addq.b    #1, (s)
  291.                 clr.w    i
  292.                 move.b    (s), i
  293.                 adda.w    i, s
  294.                 move.b    c, (s)
  295.     }
  296. }
  297.  
  298. CenterWindow(wp, h, v)
  299. register WindowPtr wp;
  300. register int h, v;
  301. {
  302.     Rect wRect;
  303.     Rect ScrnRect;
  304.     int top, left;
  305.     GrafPtr savePort;
  306.     register int dx, dy;
  307.     ScrnRect = *((Rect *) (*((Handle) CurrentA5)-116));
  308.     ScrnRect.top += MBarHeight;
  309.     GetPort(&savePort);
  310.     SetPort(wp);
  311.     wRect = wp->portRect;
  312.     LocalToGlobal(&topLeft(wRect));
  313.     LocalToGlobal(&botRight(wRect));
  314.     top = wRect.top;
  315.     left = wRect.left;
  316.     SetPort(savePort);
  317.     CenterRect(&wRect, &ScrnRect);
  318.     dx = wRect.left-ScrnRect.left;
  319.     dy = wRect.top-ScrnRect.top;
  320.     if ((h > 1) && dx) {
  321.         dx = dx*h/100;
  322.     }
  323.     if ((v > 1) && dy) {
  324.         dy = dy*h/100;
  325.     }
  326.     if (h) {
  327.         h = ScrnRect.left+dx;
  328.     }
  329.     else {
  330.         h = left;
  331.     }
  332.     if (v) {
  333.         v = ScrnRect.top+dy;
  334.     }
  335.     else {
  336.         v = top;
  337.     }
  338.     MoveWindow(wp, h, v, FALSE);
  339. }
  340.  
  341. CenterRect(RtoCent, r)
  342. register Rect *RtoCent, *r;
  343. {
  344.     int dx = MidPoint(r->left, r->right);
  345.     int dy = MidPoint(r->top, r->bottom);
  346.     dx -= MidPoint(RtoCent->left, RtoCent->right);
  347.     dy -= MidPoint(RtoCent->top, RtoCent->bottom);
  348.     OffsetRect(RtoCent, dx, dy);
  349. }
  350.  
  351. int MidPoint(a, b)
  352. register int a, b;
  353. {
  354.     return((a+b)/2);
  355. }
  356.